<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2024/6/24
 * Time: 14:36
 */

namespace app\logic\cron;


use app\common\lib\Common;
use app\common\lib\RedisQueue;
use app\common\lib\Spreadsheet;
use app\exception\IndexException;
use app\logic\BaseLogic;
use app\model\image\ImageCommandPlanModel;
use app\model\novel\NovelBusinessModel;
use app\model\novel\NovelChapterModel;
use app\model\novel\NovelSpreadModel;
use app\model\plan\PromotionPlanModel;
use app\model\plan\PromotionPlanOverseaModel;
use app\model\user\UserNovelChapterPartModel;
use app\model\user\UserPromotionPlanModel;
use plugin\admin\app\model\user\UserPromotionOverseaModel;
use support\Db;

class PlanLogic extends BaseLogic
{
    protected static $instance;

    public function __construct()
    {
        parent::__construct();
    }

    public static function getInstance()
    {
        //        if (is_object(self::$instance)) {
        //            return self::$instance;
        //        }

        return new self();
    }

    public function autoGeneratePlan()
    {
        $textLog = [];
        $timeLog = [];
        //todo 1 获取状态正常并且已经选择了指令模板的小说
        //获取水上小说
        $where      = ['task_status' => 2, 'isdel' => 0, ['ai_image_command_id', '>', 0], 'spread_type' => 1];
        $novelData1 = NovelSpreadModel::getInstance()->getWhere($where)->orderBy('created_at', 'asc')->get()->toArray();
        //获取水下小说
        $where      = ['under_status' => 1, 'isdel' => 0, ['ai_image_command_id', '>', 0], 'spread_type' => 2];
        $novelData2 = NovelSpreadModel::getInstance()->getWhere($where)->orderBy('created_at', 'asc')->get()->toArray();

        $novelData = array_merge($novelData1, $novelData2);
        foreach ($novelData as $novel) {
            $chapterData = NovelChapterModel::getInstance()->getWhere(['novel_sn' => $novel['novel_sn'], 'isdel' => 0])->get();
            foreach ($chapterData as $chapter) {
                $startTime = time();
                $createWay = 'cron_' . $novel['ai_image_command_id'];
                $count     = PromotionPlanModel::getInstance()->getWhere(['chapterid' => $chapter['id'], 'isdel' => 0, 'create_way' => $createWay])->count();
                if ($count) {
                    //创建方式和模板id一样的方案章节已经存在跳过
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-创建方式和模板id一样的方案章节已经存在跳过';
                    continue;
                }

                //todo 1-1 总结原文
                if (empty($chapter['original_content'])) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-original_content 是空值跳过';
                    continue;
                }
                if (empty($chapter['original_content_ai_command'])) {
                    $chapter['original_content_ai_command'] = getAiCommand('original_content_ai_command');
                }

                $analyzeContent = '';
                try {
                    $replaceStr     = [
                        "\r", '`', '~', '@', '#', '$', '^', '&', '*', '(', ')', '=', '|', '{', '}', '\\', '[', ']', '<', '>',
                        '《', '》', '/', '￥', '……', '（', '）', '――', '【', '】', '‘', '”', '“', '"', '\'', ' ', '「', '」'
                    ];
                    $contentText    = str_replace($replaceStr, "", $chapter['original_content']);
                    $analyzeContent = Common::generatedContent($contentText, $chapter['original_content_ai_command']);
                } catch (\Throwable $e) {
                }

                if ($analyzeContent == false) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-总结原文失败跳过';
                    continue;
                }

                //todo 1-2 总结内容分段
                if (empty($chapter['content_parts_ai_command'])) {
                    $chapter['content_parts_ai_command'] = getAiCommand('content_parts_ai_command');
                }
                $content  = '';
                $contents = '';
                foreach ([1, 2, 3] as $n) {
                    try {
                        $replaceStr  = [
                            "\r", '`', '~', '@', '#', '$', '^', '&', '*', '(', ')', '=', '|', '{', '}', '\\', '[', ']', '<', '>',
                            '《', '》', '/', '￥', '……', '（', '）', '――', '【', '】', '‘', '”', '“', '"', '\'', ' ', '「', '」'
                        ];
                        $contentText = str_replace($replaceStr, "", $analyzeContent);
                        $content     = Common::generatedContent($contentText, $chapter['content_parts_ai_command']);
                    } catch (\Throwable $e) {
                    }
                    if ($content == false) {
                        continue;
                    }

                    $contents = array_values(array_filter(explode("\n", $content)));
                    $lk       = 0;
                    foreach ($contents as $text) {
                        if (mb_strlen($text) <= 5) {
                            $lk++;
                        }
                    }
                    if ($lk >= 3) {
                        $content  = '';
                        $contents = [];
                        continue;
                    } else {
                        //满足跳出
                        break;
                    }
                }
                if ($content == false) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-分析内容分段失败跳过';
                    continue;
                }

                //todo 1-3 批量生成描述词
                if (empty($chapter['batch_prompt_ai_command'])) {
                    $chapter['batch_prompt_ai_command'] = getAiCommand('batch_prompt_ai_command');
                }
                if (empty($chapter['gptversion'])) {
                    $chapter['gptversion'] = config('param.default_gpt_version', 'gpt-4o');
                }

                $promptContent  = '';
                $promptContents = [];
                foreach ([1, 2, 3] as $n) {
                    try {
                        $contentData = [];
                        foreach ($contents as $k => $contentV) {
                            $contentData[] = (($k + 1) . '.') . preg_replace('/^\d+[\.]*/', '', $contentV);
                        }
                        $contentText   = implode("\n", $contentData);
                        $promptContent = Common::generatedBatchPrompt($contentText, $chapter['batch_prompt_ai_command'], $chapter['gptversion']);
                    } catch (\Throwable $e) {
                    }
                    if ($promptContent == false) {
                        continue;
                    }
                    $promptContents = array_values(array_filter(explode("\n", $promptContent)));

                    if (count($contents) != count($promptContents)) {
                        $promptContent  = '';
                        $promptContents = [];
                        //段落不一致，跳过
                        continue;
                    } else {
                        //满足跳出
                        break;
                    }
                }
                if (count($contents) != count($promptContents)) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-批量生成描述词段落不一致跳过';
                    //段落不一致，跳过
                    continue;
                }

                $timeLog[] = round(time() - $startTime);
                //todo 2 创建方案并更新章节内容
                $planId = false;
                try {
                    Db::connection('mysql')->beginTransaction();
                    $planId = $this->createPlan($novel, $chapter);
                    if ($planId) {
                        $update = [
                            'original_content_ai_command' => $chapter['original_content_ai_command'],
                            'analyze_content'             => $analyzeContent,
                            'content_parts_ai_command'    => $chapter['content_parts_ai_command'],
                            'content'                     => $content,
                            'batch_prompt_ai_command'     => $chapter['batch_prompt_ai_command'],
                            'prompt_content'              => $promptContent,
                            'gptversion'                  => $chapter['gptversion']
                        ];
                        NovelChapterModel::getInstance()->getWhere(['id' => $chapter['id']])->update($update);

                        NovelSpreadModel::getInstance()->getWhere(['id' => $novel['id']])->update(['status' => 1]);
                    }
                    Db::connection('mysql')->commit();
                } catch (\Throwable $e) {
                    Db::connection('mysql')->rollBack();
                }
                if ($planId == false) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-方案生成失败跳过';
                    continue;
                }

                //todo 3 加入自动生成分段的队列
                //生成唯一的请求id
                $requestId = md5(round(microtime(true) * 10000) . uniqid() . mt_rand(1000, 9999));

                // 队列名
                $queue = 'asyncPlanPart';
                // 数据，可以直接传数组，无需序列化
                $data = ['requestid' => $requestId, 'planid' => $planId, 'type' => 'all', 'from' => 'cron'];
                // 投递消息
                RedisQueue::getInstance()->sendQueue($queue, $data);

                //延迟100毫秒
                usleep(100000);
            }
        }

        if (!empty($textLog)) {
            $contentLog = date('Y-m-d H:i:s') . ":\n" . implode("\n", $textLog) . "\n" . "\n";
            file_put_contents(runtime_path('autoGeneratePlan-text.log'), $contentLog, 8);
        }
        if (!empty($timeLog)) {
            $contentLog = date('Y-m-d H:i:s') . ":\n" . implode(", ", $timeLog) . "\n" . "\n";
            file_put_contents(runtime_path('autoGeneratePlan-time.log'), $contentLog, 8);
        }

        return true;
    }

    public function autoGeneratePlanByUpload()
    {
        $textLog = [];
        $timeLog = [];
        if (is_file(runtime_path('autogenerateplan.xlsx')) == false) {
            throw new IndexException(4020, '文件不存在');
        }
        $exceldata = Spreadsheet::getInstance()->readExcelFile(runtime_path('autogenerateplan.xlsx'));
        $headers   = array_shift($exceldata);

        $commandIds = [];
        foreach ($headers as $k => $header) {
            $commandId = explode('-', $header)[0];
            if (is_numeric($commandId) == false) {
                continue;
            }
            $commandIds[$k] = $commandId;

        }

        $novels = [];
        foreach ($exceldata as $val) {
            foreach ($commandIds as $k => $commandId) {
                $val[$k] && $novels[$commandId][] = $val[$k];
            }
        }
        foreach ($novels as $commandId => $novelSns) {
            $imageCommand = ImageCommandPlanModel::getInstance()->find($commandId);
            if ($imageCommand == false) {
                continue;
            }
            $where     = [['novel_sn', 'in', $novelSns], 'isdel' => 0];
            $novelData = NovelSpreadModel::getInstance()->getWhere($where)->orderBy('created_at', 'asc')->get()->toArray();

            foreach ($novelData as $novel) {
                $novel['ai_image_command_id'] = $commandId;
                $chapterData                  = NovelChapterModel::getInstance()->getWhere(['novel_sn' => $novel['novel_sn'], 'isdel' => 0])->get();
                foreach ($chapterData as $chapter) {
                    $startTime     = time();
                    $updateChapter = [];

                    //todo 1-1 总结原文
                    if (empty($chapter['original_content'])) {
                        $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-original_content 是空值跳过';
                        continue;
                    }
                    if (empty($chapter['original_content_ai_command'])) {
                        $chapter['original_content_ai_command'] = getAiCommand('original_content_ai_command');
                    }

                    $analyzeContent = '';
                    if (empty($chapter['analyze_content'])) {
                        try {
                            $replaceStr     = [
                                "\r", '`', '~', '@', '#', '$', '^', '&', '*', '(', ')', '=', '|', '{', '}', '\\', '[', ']', '<', '>',
                                '《', '》', '/', '￥', '……', '（', '）', '――', '【', '】', '‘', '”', '“', '"', '\'', ' ', '「', '」'
                            ];
                            $contentText    = str_replace($replaceStr, "", $chapter['original_content']);
                            $analyzeContent = Common::generatedContent($contentText, $chapter['original_content_ai_command']);
                        } catch (\Throwable $e) {
                        }

                        if ($analyzeContent == false) {
                            $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-总结原文失败跳过';
                            continue;
                        }

                        $updateChapter['analyze_content']             = $analyzeContent;
                        $updateChapter['original_content_ai_command'] = $chapter['original_content_ai_command'];
                    } else {
                        $analyzeContent = $chapter['analyze_content'];
                    }

                    //todo 1-2 总结内容分段
                    if (empty($chapter['content_parts_ai_command'])) {
                        $chapter['content_parts_ai_command'] = getAiCommand('content_parts_ai_command');
                    }
                    $content  = '';
                    $contents = '';
                    if (empty($chapter['content'])) {
                        foreach ([1, 2, 3] as $n) {
                            try {
                                $replaceStr  = [
                                    "\r", '`', '~', '@', '#', '$', '^', '&', '*', '(', ')', '=', '|', '{', '}', '\\', '[', ']', '<', '>',
                                    '《', '》', '/', '￥', '……', '（', '）', '――', '【', '】', '‘', '”', '“', '"', '\'', ' ', '「', '」'
                                ];
                                $contentText = str_replace($replaceStr, "", $analyzeContent);
                                $content     = Common::generatedContent($contentText, $chapter['content_parts_ai_command']);
                            } catch (\Throwable $e) {
                            }
                            if ($content == false) {
                                continue;
                            }

                            $contents = array_values(array_filter(explode("\n", $content)));
                            $lk       = 0;
                            foreach ($contents as $text) {
                                if (mb_strlen($text) <= 5) {
                                    $lk++;
                                }
                            }
                            if ($lk >= 3) {
                                $content  = '';
                                $contents = [];
                                continue;
                            } else {
                                //满足跳出
                                break;
                            }
                        }
                        if ($content == false) {
                            $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-分析内容分段失败跳过';
                            continue;
                        }

                        $updateChapter['content']                  = implode("\n", $contents);
                        $updateChapter['content_parts_ai_command'] = $chapter['content_parts_ai_command'];
                    } else {
                        $contents = explode("\n", $chapter['content']);
                    }


                    //todo 1-3 批量生成描述词
                    if (empty($chapter['batch_prompt_ai_command'])) {
                        $chapter['batch_prompt_ai_command'] = getAiCommand('batch_prompt_ai_command');
                    }
                    if (empty($chapter['gptversion'])) {
                        $chapter['gptversion'] = config('param.default_gpt_version', 'gpt-4o');
                    }

                    $promptContent  = '';
                    $promptContents = [];
                    if (empty($chapter['prompt_content'])) {
                        foreach ([1, 2, 3] as $n) {
                            try {
                                $contentData = [];
                                foreach ($contents as $k => $contentV) {
                                    $contentData[] = (($k + 1) . '.') . preg_replace('/^\d+[\.]*/', '', $contentV);
                                }
                                $contentText   = implode("\n", $contentData);
                                $promptContent = Common::generatedBatchPrompt($contentText, $chapter['batch_prompt_ai_command'], $chapter['gptversion']);
                            } catch (\Throwable $e) {
                            }
                            if ($promptContent == false) {
                                continue;
                            }
                            $promptContents = array_values(array_filter(explode("\n", $promptContent)));

                            if (count($contents) != count($promptContents)) {
                                $promptContent  = '';
                                $promptContents = [];
                                //段落不一致，跳过
                                continue;
                            } else {
                                //满足跳出
                                break;
                            }
                        }
                        if (count($contents) != count($promptContents)) {
                            $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-批量生成描述词段落不一致跳过';
                            //段落不一致，跳过
                            continue;
                        }

                        $updateChapter['prompt_content']          = $promptContent;
                        $updateChapter['batch_prompt_ai_command'] = $chapter['batch_prompt_ai_command'];
                        $updateChapter['gptversion']              = $chapter['gptversion'];
                    }

                    $timeLog[] = round(time() - $startTime);
                    //todo 2 创建方案并更新章节内容
                    $planId = false;
                    try {
                        Db::connection('mysql')->beginTransaction();
                        $planId = $this->createPlan($novel, $chapter);
                        if ($planId) {
                            $updateChapter && NovelChapterModel::getInstance()->getWhere(['id' => $chapter['id']])->update($updateChapter);

                            NovelSpreadModel::getInstance()->getWhere(['id' => $novel['id']])->update(['status' => 1]);
                        }
                        Db::connection('mysql')->commit();
                    } catch (\Throwable $e) {
                        Db::connection('mysql')->rollBack();
                    }
                    if ($planId == false) {
                        $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-方案生成失败跳过';
                        continue;
                    }

                    //todo 3 加入自动生成分段的队列
                    //生成唯一的请求id
                    $requestId = Common::getRequestId();

                    // 队列名
                    $queue = 'asyncPlanPart';
                    // 数据，可以直接传数组，无需序列化
                    $data = ['requestid' => $requestId, 'planid' => $planId, 'type' => 'all', 'from' => 'cron'];
                    // 投递消息
                    RedisQueue::getInstance()->sendQueue($queue, $data);

                    //延迟100毫秒
                    usleep(20000);
                }
            }
        }

        if (!empty($textLog)) {
            $contentLog = date('Y-m-d H:i:s') . ":\n" . implode("\n", $textLog) . "\n" . "\n";
            file_put_contents(runtime_path('autoGeneratePlanByUpload-text.log'), $contentLog, 8);
        }
        if (!empty($timeLog)) {
            $contentLog = date('Y-m-d H:i:s') . ":\n" . implode(", ", $timeLog) . "\n" . "\n";
            file_put_contents(runtime_path('autoGeneratePlanByUpload-time.log'), $contentLog, 8);
        }
    }

    protected function createPlan($novel, $chapter)
    {
        $imageCommand = ImageCommandPlanModel::getInstance()->find($novel['ai_image_command_id']);
        if ($imageCommand == false) {
            return false;
        }
        $insertPlan = [
            'name'                  => $novel['title'] . '-' . $imageCommand['name'],
            'chapterid'             => $chapter['id'],
            'novel_sn'              => $chapter['novel_sn'],
            'musicid'               => 0,
            'timbreid'              => 92,
            'music_volume'          => 50,
            'timbre_volume'         => 50,
            'speak_speed'           => 13,
            'fontid'                => 48,
            'ai_images_nums'        => 1,
            'ai_image_command'      => $imageCommand['ai_image_command'],
            'ai_image_command_id'   => $imageCommand['id'],
            'ai_image_command_data' => urlencode(str_replace(' ', '~', json_encode($imageCommand->toArray(), 256))),
            'create_way'            => 'upload_' . $novel['ai_image_command_id'],
            'spread_type'           => $novel['spread_type'],
        ];
        $planId     = PromotionPlanModel::getInstance()->insertGetId($insertPlan);

        return $planId;
    }

    public function generateChapterContent()
    {
        $textLog = [];
        $timeLog = [];
        //todo 1 获取状态正常并且已经选择了指令模板的小说
        //获取水上小说
        $where      = ['task_status' => 2, 'isdel' => 0, ['ai_image_command_id', '>', 0], 'spread_type' => 1];
        $novelData1 = NovelSpreadModel::getInstance()->getWhere($where)->orderBy('created_at', 'asc')->get()->toArray();
        //获取水下小说
        $where      = ['under_status' => 1, 'isdel' => 0, ['ai_image_command_id', '>', 0], 'spread_type' => 2];
        $novelData2 = NovelSpreadModel::getInstance()->getWhere($where)->orderBy('created_at', 'asc')->get()->toArray();

        $novelData = array_merge($novelData1, $novelData2);
        foreach ($novelData as $novel) {
            $chapterData = NovelChapterModel::getInstance()->getWhere(['novel_sn' => $novel['novel_sn'], 'isdel' => 0])->get();
            foreach ($chapterData as $chapter) {
                //todo 1-1 总结原文
                if (empty($chapter['original_content'])) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-original_content 是空值跳过';
                    continue;
                }
                //if (empty($chapter['original_content_ai_command'])) {
                $chapter['original_content_ai_command'] = getAiCommand('original_content_ai_command');
                //}

                $analyzeContent = '';
                try {
                    $startTime                     = time();
                    $replaceStr                    = [
                        "\r", '`', '~', '@', '#', '$', '^', '&', '*', '(', ')', '=', '|', '{', '}', '\\', '[', ']', '<', '>',
                        '《', '》', '/', '￥', '……', '（', '）', '――', '【', '】', '‘', '”', '“', '"', '\'', ' ', '「', '」'
                    ];
                    $contentText                   = str_replace($replaceStr, "", $chapter['original_content']);
                    $analyzeContent                = Common::generatedContent($contentText, $chapter['original_content_ai_command']);
                    $timeLog['original_content'][] = round(time() - $startTime);
                } catch (\Throwable $e) {
                }

                if ($analyzeContent == false) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-总结原文失败跳过';
                    continue;
                }

                //todo 1-2 总结内容分段
                //if (empty($chapter['content_parts_ai_command'])) {
                $chapter['content_parts_ai_command'] = getAiCommand('content_parts_ai_command');
                //}
                $content  = '';
                $contents = '';
                foreach ([1, 2, 3] as $n) {
                    try {
                        $startTime                  = time();
                        $replaceStr                 = [
                            "\r", '`', '~', '@', '#', '$', '^', '&', '*', '(', ')', '=', '|', '{', '}', '\\', '[', ']', '<', '>',
                            '《', '》', '/', '￥', '……', '（', '）', '――', '【', '】', '‘', '”', '“', '"', '\'', ' ', '「', '」'
                        ];
                        $contentText                = str_replace($replaceStr, "", $analyzeContent);
                        $content                    = Common::generatedContent($contentText, $chapter['content_parts_ai_command']);
                        $timeLog['content_parts'][] = round(time() - $startTime);
                    } catch (\Throwable $e) {
                    }
                    if ($content == false) {
                        continue;
                    }

                    $contents = array_values(array_filter(explode("\n", $content)));
                    $lk       = 0;
                    foreach ($contents as $text) {
                        if (mb_strlen($text) <= 5) {
                            $lk++;
                        }
                    }
                    if ($lk >= 3) {
                        $content  = '';
                        $contents = [];
                        continue;
                    } else {
                        //满足跳出
                        break;
                    }
                }
                if ($content == false) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-分析内容分段失败跳过';
                    continue;
                }

                //todo 1-3 批量生成描述词
                //if (empty($chapter['batch_prompt_ai_command'])) {
                $chapter['batch_prompt_ai_command'] = getAiCommand('batch_prompt_ai_command');
                //}
                //if (empty($chapter['gptversion'])) {
                $chapter['gptversion'] = config('param.default_gpt_version', 'gpt-4o');
                //}

                $promptContent  = '';
                $promptContents = [];
                foreach ([1, 2, 3] as $n) {
                    try {
                        $startTime   = time();
                        $contentData = [];
                        foreach ($contents as $k => $contentV) {
                            $contentData[] = (($k + 1) . '.') . preg_replace('/^\d+[\.]*/', '', $contentV);
                        }
                        $contentText               = implode("\n", $contentData);
                        $promptContent             = Common::generatedBatchPrompt($contentText, $chapter['batch_prompt_ai_command'], $chapter['gptversion']);
                        $timeLog['batch_prompt'][] = round(time() - $startTime);
                    } catch (\Throwable $e) {
                    }
                    if ($promptContent == false) {
                        continue;
                    }
                    $promptContents = array_values(array_filter(explode("\n", $promptContent)));

                    if (count($contents) != count($promptContents)) {
                        $promptContent  = '';
                        $promptContents = [];
                        //段落不一致，跳过
                        continue;
                    } else {
                        //满足跳出
                        break;
                    }
                }
                if (count($contents) != count($promptContents)) {
                    $textLog[] = $novel['novel_sn'] . '-' . $chapter['id'] . '-批量生成描述词段落不一致跳过';
                    //段落不一致，跳过
                    continue;
                }

                //todo 2 更新章节内容
                try {
                    Db::connection('mysql')->beginTransaction();
                    $update = [
                        'original_content_ai_command' => $chapter['original_content_ai_command'],
                        'analyze_content'             => $analyzeContent,
                        'content_parts_ai_command'    => $chapter['content_parts_ai_command'],
                        'content'                     => $content,
                        'batch_prompt_ai_command'     => $chapter['batch_prompt_ai_command'],
                        'prompt_content'              => $promptContent,
                        'gptversion'                  => $chapter['gptversion']
                    ];
                    NovelChapterModel::getInstance()->getWhere(['id' => $chapter['id']])->update($update);

                    Db::connection('mysql')->commit();
                } catch (\Throwable $e) {
                    Db::connection('mysql')->rollBack();
                }

                //延迟100毫秒
                usleep(100000);
            }
        }

        if (!empty($textLog)) {
            $contentLog = date('Y-m-d H:i:s') . "\n" . implode("\n", $textLog) . "\n" . "\n";
            file_put_contents(runtime_path('generateChapterContent-text.log'), $contentLog, 8);
        }

        if (!empty($timeLog)) {
            $contentText = '';
            foreach ($timeLog as $key => $times) {
                $contentText .= $key . ': ' . implode(", ", $times) . "\n";
            }
            $contentLog = date('Y-m-d H:i:s') . ":\n" . $contentText . "\n" . "\n";
            file_put_contents(runtime_path('generateChapterContent-time.log'), $contentLog, 8);
        }

        return true;
    }

    public function autoGenerateOverseaWork()
    {

        $fields = [ 'novel_sn','title','main_image','platform','payment_allocate_ratio',
                    'business_id','labels','desc', 'created_at', 'app_id', 'start_time',
                    'data_source_key','total_spread_num','total_heighest_income','total_income','total_like_nums',
                    'commission','first_category','second_category','words_num','spread_type','book_id','lang',
        ];

        $bWhere = ['status'=>1,'isdel'=>0,'spread_type'=>3];
        $businessIds = NovelBusinessModel::getInstance()->getWhere($bWhere)->pluck('id')->toArray();
        $where = [
            'isdel'=>0,
            'status'=>1,
            ['business_id','in',$businessIds],
        ];

        $novelData = NovelSpreadModel::getInstance()->getWhere($where)->orderBy('start_time','asc')->limit(1)->get($fields);

        $userSn = config('app.app_env')=='prod'?'2010002120':'2010001620';
        $userPlanids = [];
        foreach ($novelData as $novel){
            foreach ([1,2,3] as $n){
                $id = $this->submitDataByOverseaNovel($novel,$userSn);
                if($id==false){
                    continue;
                }
                $userPlanids[] = $this->generateAndConsumeByOversea($id,$userSn);
            }
        }

        return $userPlanids;
    }

    protected function submitDataByOverseaNovel($novel,$userSn)
    {
        $where = ['novel_sn'=>$novel['novel_sn'],['content','<>','']];
        $chapter = NovelChapterModel::getInstance()->getWhere($where)->orderBy(Db::Raw('RAND()'))->first();
        if($chapter==false){
            return false;
        }
        //随机获取当前海外方案
        $where = ['isdel' => 0, 'status' => 1, 'lang' => $novel['lang']];
        $plan = PromotionPlanOverseaModel::getInstance()->getWhere($where)->orderBy(Db::Raw('RAND()'))->first();
        if($plan==false){
            return false;
        }

        $content = $chapter['content'];

        $parts = array_values(array_filter(explode("\n",$content)));
        $subTitles = [];
        foreach ($parts as $part){
            $content = str_replace([','], "\n",$part);
            $contents = array_values(array_filter(explode("\n",$content)));
            $subTitles[] = $contents;
        }

        //去重设置
        $settings = !empty($plan['settings']) ? json_decode($plan['settings'], true) : [];
        $settingsKeys = ['random_reduce','random_add','random_speed','random_mirror','random_hash','random_filter','random_effect','random_transition','random_enlarge'];
        foreach ($settingsKeys as $val){
            $settings[$val] = (int)(isset($settings[$val])?$settings[$val]:1);
        }

        //素材选择
        $videoRate = $plan['video_scale']??'9:16';
        $materialDatas = [];
        if(!empty($plan['material_id'])){
            $materialData = getMaterialData($plan['material_id']);
            if ($materialData) {

                //目前不考虑分辨率
                $heigh = $materialData['heigh'];
                $normal = $materialData['normal'];

                //打乱素材视频顺序
                $heigh && shuffle($heigh);
                $normal && shuffle($normal);
                $materialDatas = ['heigh'=>array_slice($heigh,0,50),'normal'=>array_slice($normal,0,100)];
            }
        }
        if(empty($materialDatas['heigh']) &&  empty($materialDatas['normal'])){
            return false;
        }

        $insert = [
            'user_sn'=>$userSn,
            'novel_sn'=>$chapter['novel_sn'],
            'chapterid'=>$chapter['id'],
            'content'=>$content,
            'planid'=>$plan['id'],
            'musicid'=>$plan['musicid']??0,
            'timbreid'=>$plan['timbreid']??0,
            'music_volume'=>!empty($plan['music_volume'])?$plan['music_volume']:10,
            'timbre_volume'=>!empty($plan['timbre_volume'])?$plan['timbre_volume']:10,
            'speak_speed'=>!empty($plan['speak_speed'])?$plan['speak_speed']:10,
            'fontid'=>$plan['fontid']??0,
            'video_rate'=>$videoRate,
            'part_content'=>json_encode(array_values($parts),256),
            'subtitle'=>json_encode($subTitles,256),

            'material_id'=>$plan['material_id']??'',
            'material_data'=>$materialDatas ? json_encode($materialDatas,256) : '',
            'settings'=>json_encode($settings),
            'font_size'=>$plan['font_size']??10,
            'caption_post_x'=>!empty($plan['caption_post_x'])?$plan['caption_post_x']:0,
            'caption_post_y'=>!empty($plan['caption_post_y'])?$plan['caption_post_y']:0,
            'type'=>2,
        ];
        $id = UserPromotionOverseaModel::getInstance()->insertGetId($insert);

        return $id;
    }

    protected function generateAndConsumeByOversea($id,$userSn)
    {
        $plan = UserPromotionOverseaModel::getInstance()->getWhere(['id' => $id])->first();
        if ($plan == false) {
            return false;
        }

        //获取该方案的段落
        $parts = json_decode($plan['part_content'], true);
        $subTitles = json_decode($plan['subtitle'], true);

        if (empty($parts)) {
            return false;
        }

        //处理素材
        $materialData = $plan['material_data'] ? json_decode($plan['material_data'], true):[];
        if(empty($materialData['heigh']) &&  empty($materialData['normal'])){
            return false;
        }

        try {
            Db::connection('mysql')->beginTransaction();
            //todo 1 插入用户推文方案
            $userPlanInsert = [
                'user_sn'       => $userSn,
                'novel_sn'      => $plan['novel_sn'] ?? '0',
                'chapterid'     => $plan['chapterid'] ?? '0',
                'planid'        => $plan['planid'],
                'part_nums'     => count($parts) ?? 0,
                'musicid'       => $plan['musicid'] ?? 0,
                'timbreid'      => $plan['timbreid'] ?? 0,
                'music_volume'  => $plan['music_volume'] ?? 10,
                'timbre_volume' => $plan['timbre_volume'] ?? 10,
                'speak_speed'   => $plan['speak_speed'] ?? 10,
                'fontid'        => $plan['fontid'] ?? 0,
                'plan_type'     => 4,
                'spread_type'   => !empty($plan['novel_sn']) ? 3 : '0',
                'video_rate'    => $plan['video_rate'] ?? '9:16',
                'overseaid'     => $plan['id'] ?? '0',

                'material_id'    => $plan['material_id'] ?? '',
                'settings'       => $plan['settings'] ?? '',
                'font_size'      => $plan['font_size'] ?? '0',
                'caption_post_x' => $plan['caption_post_x'] ?? '0',
                'caption_post_y' => $plan['caption_post_y'] ?? '0',
                'lang'           => $plan['lang'] ?? 'en',
                'material_data'  => json_encode($materialData, 256),
            ];
            $userPlanid = UserPromotionPlanModel::getInstance()->insertGetId($userPlanInsert);

            //todo 2 插入用户推文方案片段
            $userPartInserts = [];
            foreach ($parts as $k=>$part) {
                $userPartInsert = [
                    'user_sn'     => $userSn,
                    'user_planid' => $userPlanid,
                    'planid'      => $plan['planid'] ?? 0,
                    'chapterid'   => $plan['chapterid'] ?? '0',
                    'novel_sn'    => $plan['novel_sn'] ?? '0',
                    'overseaid'   => $plan['id'],
                    'content'     => $part,
                    'number'      => $k + 1,
                    'subtitle'    => json_encode($subTitles[$k] ?? [], 256),
                ];
                $userPartInserts[] = $userPartInsert;
            }
            UserNovelChapterPartModel::getInstance()->insert($userPartInserts);

            Db::connection('mysql')->commit();
        }catch (IndexException $e){
            Db::connection('mysql')->rollBack();
            return false;
        }catch (\Throwable $e){
            Db::connection('mysql')->rollBack();
            return false;
        }

        //生成唯一的请求id
        $requestId = Common::getRequestId();

        // 队列名
        $queue = 'generatedOverseaVideo';
        // 数据，可以直接传数组，无需序列化
        $data = ['requestid' => $requestId, 'user_planid' => $userPlanid];
        // 投递消息
        RedisQueue::getInstance()->sendQueue($queue, $data);

        return $userPlanid;
    }
}